'''
Created on 21 jan 2010

@author: rlindeman
'''
import unittest
import time
import random

import test.file
import rai.logger.logger as logger
from rai.sem.qasystem import *

class TestQASystemPerformance(unittest.TestCase):
    
    PropNs = ["Angus", "Pat", "Irene", "Cyril", "John", "Vincent", "Joe", "Mary", "Suzie", "Bob"]
    IVs = ["bark", "walk", "smell", "die", "sleep"]
    TVs = ["chase", "see" , "love", "lift", "hit", "drive", "clean"]
    
    def setUp(self):
        self.basedir = test.file.__path__[0]
        self.org_grammar = "file:" + self.basedir + "\\org.event.fcfg"
        self.qaSystem = QASystem(grammar_location=self.org_grammar)
        self.sents = []
        
    def generateText(self, linecount, filename):
        """
            Generates a random text, the number of sentences is equal to the given linecount
        """
        self.generateSents()
        if (linecount > self.sents):
            raise ValueError("line count is larger than the total sentences count")
        indices_list = random.sample(xrange(len(self.sents)), linecount)
        text_file = open(filename, "w")
        for index in indices_list:
            text_file.write(self.sents[index]+"\n")
        text_file.close()      
        
        # NP * IV
        # NP * TV * NP
        # NP * DTV * NP * PP
        
    def generateSents(self):
        """
            Generate all possible sentences using fixed nouns and verbs
        """
        if (len(self.sents) > 0):
            return
        self.sents = []
        # IVs
        for propn in TestQASystemPerformance.PropNs:
            for iv in map(lambda x: str(x)+"s", TestQASystemPerformance.IVs):
                self.sents.append("%s %s" % (propn, iv))
        # TVs
        for propn in TestQASystemPerformance.PropNs:
            for tv in map(lambda x: str(x)+"s", TestQASystemPerformance.TVs):
                for propn2 in TestQASystemPerformance.PropNs:
                    self.sents.append("%s %s %s" % (propn, tv, propn2))
        
    def _testStats(self):
        self.generateSents()
        print "Total sents: " + str(len(self.sents))
        propnCount = len(TestQASystemPerformance.PropNs)
        ivCount = len(TestQASystemPerformance.IVs)
        tvCount = len(TestQASystemPerformance.TVs)

        ivSents = propnCount * ivCount
        tvSents = propnCount * tvCount * propnCount
        print "IV sents " + str(ivSents)
        print "TV sents " + str(tvSents)
        totalSents = ivSents + tvSents
        indices_list = random.sample(xrange(len(self.sents)), 10)
        text_file = open("write_it.txt", "w")
        for index in indices_list:
            text_file.write(self.sents[index]+"\n")
        text_file.close() 
        
    def testPerformance(self):
        text_file = open("timingtotals1.txt", "w")
        repeat = 20
        first_range = xrange(10, 110, 10)
        for linecount in first_range:
            print "TEST %s lines" % (linecount,)
            avg_totals =self.executeBatch(linecount, repeat)
            line = "\t".join(map(lambda x: str(x), avg_totals))
            #print line
            text_file.write(line+"\n")
        text_file.close()         

        text_file = open("timingtotals2.txt", "w")
        repeat = 20
        first_range = xrange(110, 210, 10)
        for linecount in first_range:
            print "TEST %s lines" % (linecount,)
            avg_totals =self.executeBatch(linecount, repeat)
            line = "\t".join(map(lambda x: str(x), avg_totals))
            #print line
            text_file.write(line+"\n")
        text_file.close()         

        text_file = open("timingtotals3.txt", "w")
        repeat = 20
        first_range = xrange(210, 310, 10)
        for linecount in first_range:
            print "TEST %s lines" % (linecount,)
            avg_totals =self.executeBatch(linecount, repeat)
            line = "\t".join(map(lambda x: str(x), avg_totals))
            #print line
            text_file.write(line+"\n")
        text_file.close()         

        text_file = open("timingtotals4.txt", "w")
        repeat = 20
        first_range = xrange(310, 410, 10)
        for linecount in first_range:
            print "TEST %s lines" % (linecount,)
            avg_totals =self.executeBatch(linecount, repeat)
            line = "\t".join(map(lambda x: str(x), avg_totals))
            #print line
            text_file.write(line+"\n")
        text_file.close() 
        print "TEST FINISHED"

        
    def executeBatch(self, linecount, repeat):
        totals = [0,0,0,0,0,0,0,0]
        count = 0
        max = repeat
        # total = ParseFacts + Proof
        # ParseFacts = chunker + grammar + other
        # grammar = addfact + parse
        #line = "Sents\nParseFacts\tchunker\tgrammar\taddfact\tparse\tProof\tprover"
        #text_file.write(line+"\n")
        while count < max:
            timing_list = self.executePerformance(linecount)
            self.assertEquals(len(timing_list),len(totals))
            totals = map(lambda x, y: x+y, totals,timing_list)
            count = count + 1
        avg_totals = map(lambda x: x/repeat, totals)
        return avg_totals
        
    def executePerformance(self, linecount):
        self.qaSystem = QASystem(grammar_location=self.org_grammar)
        filename = "performance%s.txt" % (linecount,)
        t0 = time.clock()
        self.generateText(linecount, filename)
        
        t1 = time.clock()
        self.qaSystem.parseFacts(facts_location=filename)
        t2 = time.clock()
        # eventfacts should have this number of parsable sentences        
        self.assertEquals(len(self.qaSystem.logic_expressions), linecount) 
        # add general rule
        #self.qaSystem.logic_expressions.extend(self.getGeneralRules())
        t3 = time.clock()
        question = "somebody loves Bob"
        self.qaSystem.question(question)
        proofFound = self.qaSystem.answer()
        t4 = time.clock()
        #genSampleTextTime = t1 - t0
        parseFactsTime = t2 - t1
        proverTime = t4 - t3
        #print "SampleText " + str(genSampleTextTime)
        #print "ParseFacts " + str(parseFactsTime)
        #print "+chunker   " + str(self.qaSystem.timing["chunker"])
        #print "+grammar   " + str(self.qaSystem.timing["grammar"])
        #print " +addfact  " + str(self.qaSystem.timing["grammar_addfact"])
        #print " +parse    " + str(self.qaSystem.timing["grammar_parse"])
        #print "Proof      " + str(proverTime)
        #print "+prover    " + str(self.qaSystem.timing["prover"])
        timing_list = []
        #timing_list.append(genSampleTextTime)
        timing_list.append(linecount)
        timing_list.append(parseFactsTime)
        timing_list.append(self.qaSystem.timing["chunker"])
        timing_list.append(self.qaSystem.timing["grammar"])
        timing_list.append(self.qaSystem.timing["grammar_addfact"])
        timing_list.append(self.qaSystem.timing["grammar_parse"])
        timing_list.append(proverTime)
        timing_list.append(self.qaSystem.timing["prover"])
        return timing_list
             
if __name__ == "__main__":
    unittest.main()        